﻿using BCCommon;
using BCEntity.Sim.Admin.AdminPermissionRecord;
using Dapper;
using System;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;

namespace BCData.Sim.Admin.AdminPermissionRecord
{
    public class AdminPermissionRecordData : IAdminPermissionRecordData
    {
        private readonly IDatabaseContext databaseContext;
        private const string QUERY = @"SELECT A.AdminPermissionRecordId,A.AdminId,B.FullName,A.PermissionCode,C.PermissionName,A.EnabledInsert,
                                            A.EnabledUpdate,A.EnabledDelete,A.EnabledSelect,A.DepartmentId,A.StaffOrganizationMappingRecordId
                                        FROM AdminPermissionRecord A
                                        INNER JOIN Admin B ON A.AdminId=B.AdminId
                                        INNER JOIN AdminPermissionConfig C ON A.PermissionCode=C.PermissionCode";

        private const string QUERY_DEPARTMENT = @"SELECT A.AdminPermissionRecordId,A.AdminId,B.DepartmentName,A.PermissionCode,C.PermissionName,A.EnabledInsert,
                                            A.EnabledUpdate,A.EnabledDelete,A.EnabledSelect,A.DepartmentId,C.PermissionLevel,A.StaffOrganizationMappingRecordId
                                        FROM AdminPermissionRecord A
                                        INNER JOIN Department B ON A.DepartmentId=B.DepartmentId
                                        INNER JOIN AdminPermissionConfig C ON A.PermissionCode=C.PermissionCode";
        public AdminPermissionRecordData(IDatabaseContext databaseContext)
        {
            this.databaseContext = databaseContext;
        }

        public async Task<AdminPermissionRecordEntity> Add(AdminPermissionRecordEntity entity)
        {
            string sql = SqlCommands.GetInsertSql("AdminPermissionRecord", new string[] {  "PermissionCode", "EnabledInsert", "EnabledUpdate",
                "EnabledDelete","EnabledSelect","AdminId","StaffOrganizationMappingRecordId"});
            sql = string.Format("{0} {1} WHERE A.AdminPermissionRecordId=LAST_INSERT_ID()", sql, QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PermissionCode", entity.PermissionCode, DbType.AnsiString, size: 150);
            parameters.Add("?EnabledInsert", entity.EnabledInsert, DbType.Boolean);
            parameters.Add("?EnabledUpdate", entity.EnabledUpdate, DbType.Boolean);
            parameters.Add("?EnabledDelete", entity.EnabledDelete, DbType.Boolean);
            parameters.Add("?EnabledSelect", entity.EnabledSelect, DbType.Boolean);
            parameters.Add("?AdminId", entity.AdminId, DbType.Int64);
            parameters.Add("?StaffOrganizationMappingRecordId", entity.StaffOrganizationMappingRecordId, DbType.Int32);
            return await this.databaseContext.Master.QueryFirstOrDefaultAsync<AdminPermissionRecordEntity>(sql, parameters, databaseContext.Transaction);
        }


        public async Task<AdminPermissionRecordEntity> Update(AdminPermissionRecordEntity entity)
        {
            string sql = SqlCommands.GetUpdateSql("AdminPermissionRecord", new string[] { "StaffOrganizationMappingRecordId","AdminId", "PermissionCode",
                "EnabledInsert", "EnabledUpdate", "EnabledDelete","EnabledSelect"}, new string[] { "AdminPermissionRecordId" });
            sql = string.Format("{0} {1} WHERE A.AdminPermissionRecordId=?AdminPermissionRecordId", sql, QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?AdminPermissionRecordId", entity.AdminPermissionRecordId, DbType.Int64, size: 20);
            parameters.Add("?StaffOrganizationMappingRecordId", entity.StaffOrganizationMappingRecordId, DbType.Int32);
            parameters.Add("?AdminId", entity.AdminId, DbType.Int64, size: 20);
            parameters.Add("?PermissionCode", entity.PermissionCode, DbType.AnsiString, size: 150);
            parameters.Add("?EnabledInsert", entity.EnabledInsert, DbType.Boolean);
            parameters.Add("?EnabledUpdate", entity.EnabledUpdate, DbType.Boolean);
            parameters.Add("?EnabledDelete", entity.EnabledDelete, DbType.Boolean);
            parameters.Add("?EnabledSelect", entity.EnabledSelect, DbType.Boolean);
            return await this.databaseContext.Master.QueryFirstOrDefaultAsync<AdminPermissionRecordEntity>(sql, parameters, databaseContext.Transaction);
        }

        public async Task<bool> CheckExists(string permissionCode)
        {
            string sql = @"SELECT 1 FROM AdminPermissionRecord WHERE PermissionCode=?PermissionCode LIMIT 1";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PermissionCode", permissionCode, DbType.AnsiString, size: 150);
            return await this.databaseContext.Slave.ExecuteScalarAsync(sql, parameters) != null;
        }

        public async Task<bool> CheckExists(long adminId, string permissionCode)
        {
            string sql = @"SELECT 1 FROM AdminPermissionRecord WHERE AdminId=?AdminId AND PermissionCode=?PermissionCode LIMIT 1";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?AdminId", adminId, DbType.Int64, size: 20);
            parameters.Add("?PermissionCode", permissionCode, DbType.AnsiString, size: 150);
            return await this.databaseContext.Slave.ExecuteScalarAsync(sql, parameters) != null;
        }

        public async Task<AdminPermissionRecordEntity> GetEntity(long adminId, string permissionCode)
        {
            string sql = string.Format("{0} WHERE A.AdminId=?AdminId AND A.PermissionCode=?PermissionCode LIMIT 1", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?AdminId", adminId, DbType.Int64, size: 20);
            parameters.Add("?PermissionCode", permissionCode, DbType.AnsiString, size: 150);
            return await this.databaseContext.Slave.QueryFirstOrDefaultAsync<AdminPermissionRecordEntity>(sql, parameters);
        }

        public async Task<IEnumerable<AdminPermissionRecordEntity>> GetList(long staffOrganizationMappingRecordId)
        {
            string sql = string.Format("{0} WHERE A.StaffOrganizationMappingRecordId=?StaffOrganizationMappingRecordId", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?StaffOrganizationMappingRecordId", staffOrganizationMappingRecordId, DbType.Int64, size: 20);
            return await this.databaseContext.Slave.QueryAsync<AdminPermissionRecordEntity>(sql, parameters);
        }

        public async Task<IEnumerable<AdminPermissionRecordEntity>> GetList(string permissionCode)
        {
            string sql = string.Format("SELECT AdminPermissionRecordId,AdminId,PermissionCode,DepartmentId FROM AdminPermissionRecord WHERE PermissionCode=?PermissionCode");
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PermissionCode", permissionCode, DbType.AnsiString, size: 150);
            return await this.databaseContext.Slave.QueryAsync<AdminPermissionRecordEntity>(sql, parameters);
        }

        #region 部门权限

        public async Task<AdminPermissionRecordEntity> InsertDepartmentPermissionRecordASync(AdminPermissionRecordEntity entity)
        {
            string sql = SqlCommands.GetInsertSql("AdminPermissionRecord", new string[] {  "PermissionCode", "EnabledInsert", "EnabledUpdate",
                "EnabledDelete","EnabledSelect","DepartmentId"});
            sql = string.Format("{0} {1} WHERE A.AdminPermissionRecordId=LAST_INSERT_ID();", sql, QUERY_DEPARTMENT);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PermissionCode", entity.PermissionCode, DbType.AnsiString, size: 150);
            parameters.Add("?EnabledInsert", entity.EnabledInsert, DbType.Boolean);
            parameters.Add("?EnabledUpdate", entity.EnabledUpdate, DbType.Boolean);
            parameters.Add("?EnabledDelete", entity.EnabledDelete, DbType.Boolean);
            parameters.Add("?EnabledSelect", entity.EnabledSelect, DbType.Boolean);
            parameters.Add("?DepartmentId", entity.DepartmentId, DbType.Int32);
            return await this.databaseContext.Master.QueryFirstOrDefaultAsync<AdminPermissionRecordEntity>(sql, parameters, databaseContext.Transaction);
        }

        public async Task<AdminPermissionRecordEntity> GetEntityByDepartmentIdAsync(int departmentId, string permissionCode)
        {
            string sql = string.Format("{0} WHERE A.DepartmentId=?DepartmentId AND A.PermissionCode=?PermissionCode LIMIT 1", QUERY_DEPARTMENT);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?DepartmentId", departmentId, DbType.Int64, size: 20);
            parameters.Add("?PermissionCode", permissionCode, DbType.AnsiString, size: 150);
            return await this.databaseContext.Slave.QueryFirstOrDefaultAsync<AdminPermissionRecordEntity>(sql, parameters);
        }


        public async Task<IEnumerable<AdminPermissionRecordEntity>> GetDepartmentPermissionRecordListAsync(int departmentId)
        {
            string sql = string.Format("{0} WHERE A.DepartmentId=?DepartmentId ORDER BY C.PermissionPathCode ASC", QUERY_DEPARTMENT);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?DepartmentId", departmentId, DbType.Int64, size: 20);
            return await this.databaseContext.Slave.QueryAsync<AdminPermissionRecordEntity>(sql, parameters);
        }

        public async void ClearDepartmentPermissionAsync(int departmentId)
        {
            string sql = @"DELETE FROM AdminPermissionRecord WHERE DepartmentId=?DepartmentId";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?DepartmentId", departmentId, DbType.Int32);
            await this.databaseContext.Master.ExecuteAsync(sql, parameters, databaseContext.Transaction);
        }
        public async void ClearPermissionAsync(List<string> permissionCodes, int departmentId)
        {
            string sql = @"DELETE FROM AdminPermissionRecord WHERE DepartmentId=?DepartmentId AND FIND_IN_SET(PermissionCode,?PermissionCodes)";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?DepartmentId", departmentId, DbType.Int32);
            parameters.Add("?PermissionCodes", string.Join(',', permissionCodes), DbType.AnsiString);
            await this.databaseContext.Master.ExecuteAsync(sql, parameters, databaseContext.Transaction);
        }
        public async Task<bool> DeleteDepartmentPermissionAsync(AdminPermissionRecordEntity entity)
        {
            string sql;
            if (!entity.EnabledDelete && !entity.EnabledInsert && !entity.EnabledSelect && !entity.EnabledUpdate)
            {
                //如果部门权限取消增、删、改、查权限，应删除该节点权限
                sql = this.GetDeleteDepartmentPermissionSql(entity, out DynamicParameters departmentParameters);
                await this.databaseContext.Master.ExecuteAsync(sql, departmentParameters, databaseContext.Transaction);
                //如果部门权限取消增、删、改、查权限，应删除员工该节点权限
                sql = this.GetBatchDeleteAdminPermissionSql(entity, out DynamicParameters parameters);
                return await this.databaseContext.Master.ExecuteAsync(sql, parameters, databaseContext.Transaction) > 0;
            }
            else
            {
                sql = this.GetUpdateDepartmentPermissionSql(entity, out DynamicParameters adminParameters);
                await this.databaseContext.Master.ExecuteAsync(sql, adminParameters, databaseContext.Transaction);
                sql = this.GetBatchUpdateAdminPermissionSql(entity, out DynamicParameters parameters);
                return await this.databaseContext.Master.ExecuteAsync(sql, parameters, databaseContext.Transaction) > 0;
            }
            
        }

        private string GetDeleteDepartmentPermissionSql(AdminPermissionRecordEntity entity, out DynamicParameters parameters)
        {
            string sql = @"DELETE FROM AdminPermissionRecord WHERE DepartmentId=?DepartmentId AND PermissionCode=?PermissionCode;";
            parameters = new DynamicParameters();
            parameters.Add("?PermissionCode", entity.PermissionCode, DbType.AnsiString, size: 150);
            parameters.Add("?DepartmentId", entity.DepartmentId, DbType.Int32);
            return sql;
        }

        private string GetBatchDeleteAdminPermissionSql(AdminPermissionRecordEntity entity, out DynamicParameters parameters)
        {
            string sql = @"DELETE FROM AdminPermissionRecord WHERE AdminId IN(SELECT AdminId FROM StaffOrganizationMappingRecord WHERE DepartmentId=?DepartmentId) AND PermissionCode=?PermissionCode;";
            parameters = new DynamicParameters();
            parameters.Add("?PermissionCode", entity.PermissionCode, DbType.AnsiString, size: 150);
            parameters.Add("?DepartmentId", entity.DepartmentId, DbType.Int32);
            return sql;
        }

        private string GetUpdateDepartmentPermissionSql(AdminPermissionRecordEntity entity, out DynamicParameters parameters)
        {
            string sql = SqlCommands.GetUpdateSql("AdminPermissionRecord", new string[] {  "PermissionCode", "EnabledInsert", "EnabledUpdate",
                "EnabledDelete","EnabledSelect"}, new string[] { "DepartmentId", "AdminPermissionRecordId" });
            parameters = new DynamicParameters();
            parameters.Add("?AdminPermissionRecordId", entity.AdminPermissionRecordId, DbType.Int64, size: 20);
            parameters.Add("?PermissionCode", entity.PermissionCode, DbType.AnsiString, size: 150);
            parameters.Add("?EnabledInsert", entity.EnabledInsert, DbType.Boolean);
            parameters.Add("?EnabledUpdate", entity.EnabledUpdate, DbType.Boolean);
            parameters.Add("?EnabledDelete", entity.EnabledDelete, DbType.Boolean);
            parameters.Add("?EnabledSelect", entity.EnabledSelect, DbType.Boolean);
            parameters.Add("?DepartmentId", entity.DepartmentId, DbType.Int32);
            return sql;
        }

        private string GetBatchUpdateAdminPermissionSql(AdminPermissionRecordEntity entity, out DynamicParameters parameters)
        {
            string sql = @"Update AdminPermissionRecord SET  EnabledInsert=?EnabledInsert,EnabledUpdate=?EnabledUpdate,EnabledDelete=?EnabledDelete,EnabledSelect=?EnabledSelect WHERE AdminId in(SELECT AdminId FROM StaffOrganizationMappingRecord WHERE DepartmentId=?DepartmentId) AND PermissionCode=?PermissionCode";
            parameters = new DynamicParameters();
            parameters.Add("?PermissionCode", entity.PermissionCode, DbType.AnsiString, size: 150);
            parameters.Add("?EnabledInsert", entity.EnabledInsert, DbType.Boolean);
            parameters.Add("?EnabledUpdate", entity.EnabledUpdate, DbType.Boolean);
            parameters.Add("?EnabledDelete", entity.EnabledDelete, DbType.Boolean);
            parameters.Add("?EnabledSelect", entity.EnabledSelect, DbType.Boolean);
            parameters.Add("?DepartmentId", entity.DepartmentId, DbType.Int32);
            return sql;
        }

        public async Task<bool> CheckDepartmenntExists(int departmentId, string permissionCode)
        {
            string sql = @"SELECT 1 FROM AdminPermissionRecord WHERE DepartmentId=?DepartmentId AND PermissionCode=?PermissionCode LIMIT 1";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?DepartmentId", departmentId, DbType.Int64, size: 20);
            parameters.Add("?PermissionCode", permissionCode, DbType.AnsiString, size: 150);
            return await this.databaseContext.Slave.ExecuteScalarAsync(sql, parameters) != null;
        }

        public async Task<AdminPermissionRecordEntity> UpdateDepartmentPermissionAsync(AdminPermissionRecordEntity entity)
        {
            string sql = SqlCommands.GetUpdateSql("AdminPermissionRecord", new string[] { "DepartmentId", "PermissionCode", "EnabledInsert", "EnabledUpdate",
                "EnabledDelete","EnabledSelect"}, new string[] { "AdminPermissionRecordId" });
            sql = string.Format("{0} {1} WHERE A.AdminPermissionRecordId=?AdminPermissionRecordId", sql, QUERY_DEPARTMENT);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?AdminPermissionRecordId", entity.AdminPermissionRecordId, DbType.Int64, size: 20);
            parameters.Add("?DepartmentId", entity.DepartmentId, DbType.Int32, size: 20);
            parameters.Add("?PermissionCode", entity.PermissionCode, DbType.AnsiString, size: 150);
            parameters.Add("?EnabledInsert", entity.EnabledInsert, DbType.Boolean);
            parameters.Add("?EnabledUpdate", entity.EnabledUpdate, DbType.Boolean);
            parameters.Add("?EnabledDelete", entity.EnabledDelete, DbType.Boolean);
            parameters.Add("?EnabledSelect", entity.EnabledSelect, DbType.Boolean);
            return await this.databaseContext.Master.QueryFirstOrDefaultAsync<AdminPermissionRecordEntity>(sql, parameters, databaseContext.Transaction);
        }

        #endregion
    }
}
